//
//  ReadMapper.cpp
//  germ
//
//  Created by Vinicio Reynoso on 4/3/2010.
//  Purpose: class representing a kmer-decomposed sequence
//


#ifndef __germ__ReadMapper__
#define __germ__ReadMapper__

#include <fstream>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <stdint.h>
#include "TabFile.h"
#include <time.h>
#include <iomanip>

using namespace std;

class ReadMapper{
  
public:
  typedef uint32_t u32;
  typedef uint64_t u64;
  typedef vector<u64> v64;
  typedef vector<u32> v32;
  typedef vector<bool> vBool;
  
  // K-mer information
  v64 ry_kmers;		//stores the ry for each kmer
  v64 ws_kmers;		//stores the ws for each kmer
  vector<int> locs;			//stores the locs for each kmer.
	
  // Protein information
  vector<vector<int> > protein_ranges;
  vector<string> protein_syns;		//stores unique identifiers for the proteins
  vector<string> protein_names;		//stores gene names of each protein
  vector<char> protein_strand;	//stores which strand the gene is located on, either '+' or '-'
  vector<int> protein_eHits;		//stores the number of exact mappings for each protein
  vector<int> protein_cHits;		//stores the number of close mappings for each protein
  vector<string> protein_products;	//stores the product info for each protein
  
  // RNA information
  vector<vector<int> > rna_ranges;
  vector<string> rna_syns;		//stores unique identifiers for the rna
  vector<string> rna_names;		//stores the gene names of each rna
  vector<char> rna_strand;	//stores which strand the gene is located on, either '+' or '-'
  vector<int> rna_eHits;		//stores the the number of exact mappings for each rna
  vector<int> rna_cHits;		//stores the number of close mappings for each rna
  vector<string> rna_products;	//stores the product info for each rna
  
  // Constructor/Destructor
  ReadMapper(int prefix_size);	//only makes vectors for binning the sequence
  ~ReadMapper(void);
  
  // Public functions
  void load_seq(int kmersize, string fna_file, string seqFileDir, bool annotate);	//clears data and loads the new sequence
  void map_reads(v64& ry_reads, v64& ws_reads, vBool& mapped);	//looks for and records all exact matches only
  void map_close_reads(v64& ry_reads, v64& ws_reads, vBool& mapped, int threshold);	//bins the sequence based on ry-prefixes, then looks for close matches in bins whose prefix is 1 mismatch from the read ry-prefix
  void filter_mappings(void);		//sorts read mappings and then filters them, which are put in _fmapped_* vectors
  void filter_mappings(string& file);	//loads and erases mappings from file, filters them, and then prints them back to file. CAUTION: Any present mappings are erased!
  void load_mappings(string& file, bool sorted);	//loads mappings from file. does not sort them, but sets _mappings_sorted = sorted. CAUTION: Any present mappings are erased!
  void sort_mappings(void);	//sorts whatever mappings are found in the _mapped_* vectors, if _mappings_sorted = false
  void reset_counts(void);	//resets counters to zero, and clears all mappings. should be used before mapping a new read set
  void write_mappings(string& file, bool filtered);	//writes the contents of _fmapped_* or _mapped_* vectors to the passed file
  void write_gene_hits(string& file);		//writes the gene hits to file, see method for file header
  void write_seq_hits(string& file);	//writes all the sequence hits to file, see method for file header
  
  // Accessors
  long int total_hits(void){ return _n_fexact + _n_fclose; }
  long int n_close_hits(void){ return _n_fclose; }	//value is set after filtering mappings
  long int n_exact_hits(void){ return _n_fexact; }	//value is set after mapping reads exactly
  long int n_eNC_hits(void){ return _n_eNCoding_hits; }	//value is set after calling write_seq_hits()
  long int n_cNC_hits(void){ return _n_cNCoding_hits; }	//value is set after calling write_seq_hits()
  long int n_eP_hits(void){ return _n_exact_prot_hits; }	//value is set after calling write_seq_hits()
  long int n_cP_hits(void){ return _n_close_prot_hits; }	//value is set after calling write_seq_hits()
  long int n_eR_hits(void){ return _n_exact_rna_hits; }	//value is set after calling write_seq_hits()
  long int n_cR_hits(void){ return _n_close_rna_hits; }	//value is set after calling write_seq_hits()
  int secs_spent_mapping(void){ return _t_spent_mapping; }
  string accession(void){ return _accession; }
  string seq(void){ return _seq_source; }
  
private:
  // For 'binning' the sequence based on ry prefixes
  int _prefix_size;		//the size of the purine/pyrimidine prefix used to bin the sequence
  u64 _prefix_bit_mask;		//will consist of _prefix_size contiguous 'on' bits
  u32 _n_poss_prefixes;	//number of possible purine/pyrimidine prefixes= 2^(prefix size)
  vBool _prsnt_prefixes;	//keeps track of which ry-prefixes are present in the sequence
  vector<vector<unsigned int>*> _bins;	//each bin holds the indices of kmers with a particular ry-prefix
  vector<int> _bin_sizes;			//holds the size of each bin before 1 transversion redundancy is built in
  int _t_spent_mapping;	//hold how many seconds it took to map reads, gets reset in _reset_data(); and reset_counts();
  string _seq_source;		//where the sequence entity comes from
  string _FASTA_file;		//name of the fasta file containing the sequence "accession.fna"
  string _fasta_header;	//first line of the fasta file
  string _accession;		//the accession number for the sequence
  string _ptt_file;		//name of the file containing the protein information
  string _rnt_file;		//name of the file containing the rna information
  string _seq_files_Dir;	//directory were the sequence files are located
  int _seq_length;		//length of the sequence, starts from position 1
  int _kmer_size;			//size of the kmers by which the sequence is decomposed
  int _n_kmers;			//number of kmers that were made from the sequence
  long int _n_close;		//number of unfiltered close mappings
  long int _n_fclose;		//number of filtered close mappings
  long int _n_fexact;		//number of filtered exact mappings
  long int _n_exact_dup;	//number of times a read mapped more than once, these exact mappings will be filtered out
  int _n_proteins;		//number of proteins encoded in the sequence
  long int _n_exact_prot_hits;	//number of times a read mapped onto the coding strand of a gene for a protein exactly
  long int _n_close_prot_hits; 	//number of times a read mapped onto the coding strand of a gene for a protein closely
  int _n_rna;				//number of rna genes encoded in the sequence
  long int _n_exact_rna_hits;	//number of times a read mapped onto the coding strand of a gene for a rna exactly
  long int _n_close_rna_hits;	//number of times a read mapped onto the coding strand of a gene for a rna closely
  long int _n_eNCoding_hits;	//number of times a read mapped onto a non-coding region exactly
  long int _n_cNCoding_hits;	//number of times a read mapped onto a non-coding region closely
  bool _isCircular;	//true if the sequence is circular, false otherwise
  bool _isAnnotated;	//true if the sequence was annotated
  bool _seqLoaded;	//true if a sequence was loaded
  bool _mappings_sorted;	//true if the read mappings have been sort by ry, id, and mismatch number
  
  // For holding mapping information, _fmapped_* vectors hold filtered mappings
  v64 _mapping_ry, _fmapping_ry;
  v64 _mapping_ws, _fmapping_ws;
  vector<int> _mapping_mm, _fmapping_mm;
  vector<int> _mapping_loc, _fmapping_loc;
  vector<string> _mapping_gene, _fmapping_gene;
  vector<char> _mapping_gene_strand, _fmapping_gene_strand;
  vector<string> _mapping_accession, _fmapping_acession;
  vector<string> _mapping_org, _fmapping_org;
  
  // Private functions
  void _reset_data(void);	//clears all kmer info, protein info, rna info, mapping info, and counts
  bool _check_bins(u64 ry_read, u64 ws_read, u32 prefix, int threshold);	//looks for close matches in a bin
  void _record_mapping(u64 ry_read, u64 ws_read, int loc, int mm);	//adds a read mapping to the _mapped_* vectors
  void _record_best_mappings(long int left, long int right);	//writes the closest read-mapping in each organism to _fmapped_* vectors that is found at indices [left, right]
  void _annotate_seq(void);	//records protein and rna info
  void _genes_hit(int loc, vector<string>& genes_hit, vector<char>& strand_of_gene_hit, bool close);	//determines if a read mapped onto any gene's coding region, and increments hit counters
  void _sort_kmer_int_pairs(int left, int right, bool ry, bool ws);		//used to sort kmer ry-id integer pairs between [left,right] based on either ry_ints or id_ints
  void _sort_mappings(long int left, long int right, bool ry, bool ws, bool mm);	//used to sort mappings between [left,right] based either on ry, id, or mismatch number
};


#endif /* defined(__germ__ReadMapper__) */
